#!/usr/bin env python
# -*- coding: utf-8 -*-
###########################################################################
#   Copyright (C) 2008 by Serj Poltavsky                                  #
#   serge.uliss at gmail.com                                              #
#                                                                         #
#   This program is free software; you can redistribute it and/or modify  #
#   it under the terms of the GNU General Public License as published by  #
#   the Free Software Foundation; either version 3 of the License, or     #
#   (at your option) any later version.                                   #
#                                                                         #
#   This program is distributed in the hope that it will be useful,       #
#   but WITHOUT ANY WARRANTY; without even the implied warranty of        #
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
#   GNU General Public License for more details.                          #
#                                                                         #
#   You should have received a copy of the GNU General Public License     #
#   along with this program. If not, see <http://www.gnu.org/licenses/>   #
###########################################################################

import os
import sys
import subprocess

class MediaInfo(object):
    def __init__(self, src):
        self.src = src
        self.__info = {}
        self.update()

    def get_info(self):
        return self.__info

    def get_src(self):
        return self.__src

    def set_src(self, src):
        if src is not None and not os.path.exists(src):
            raise ValueException('File not exists: "%s"' %(src))
        self.__src = src

    def update(self):
        if self.src is None:
            return

        cmd = ['ffmpeg', '-i', self.src]

        if __debug__:
            print >>sys.stderr, 'Getting file information from "%s"' % self.src
            print >>sys.stderr, " ".join(cmd)

        try:
            lines = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[1].split("\n")
        except OSError, e:
            print >>sys.stderr, "Can't get file information..."

        for line in lines:
            if "Unknown format" in line:
                raise RuntimeError("Unknown media format")

        self.update_audio(lines)
        self.update_duration(lines)
        self.update_video(lines)

    def update_audio(self, lines):
        #FFmpeg version SVN-r16238: "Audio: ac3, 48000 Hz, stereo, s16, 224 kb/s"
        key = 'Audio: '
        for line in lines:
            pos = line.find(key)
            if pos == -1:
                continue
            #ac3, 48000 Hz, stereo, s16, 224 kb/s"
            params = line[pos + len(key):].split(", ")
            self.__info['audio'] = {}
            self.__info['audio']['codec'] = params[0]
            #48000 Hz
            self.__info['audio']['samplerate'] = int(params[1].split()[0])
            self.__info['audio']['channels'] = params[2]
            #224 kb/s
            self.__info['audio']['bitrate'] = int(params[4].split()[0])

    def update_duration(self, lines):
        #Duration: 00:04:31.00, start: 0.184656, bitrate: 3162 kb/s
        key = 'Duration: '
        for line in lines:
            pos = line.find(key)
            if pos == -1:
                continue
            #00:04:31.00, start: 0.184656, bitrate: 3162 kb/s
            dur = line[pos + len(key):].split(', ')
            self.__info['duration_str'] = dur[0]
            #00:04:31.00
            time = dur[0].split(':')
            self.__info['duration'] = int(time[0]) * 3600 + int(time[1]) * 60 + int(time[2][0:2])
            #bitrate: 3162 kb/s
            self.__info['bitrate'] = int(dur[2].split()[1])

    def update_video(self, lines):
        #2.350000 =Panavision (235:100)
        #2.063888
        #1.777777 =Widescreen (16:9)
        #1.555555
        #1.333333 =Normal (4:3)

        #FFmpeg version SVN-r16238: Video: mpeg2video, yuv420p, 352x576 [PAR 24:11 DAR 4:3], 2457 kb/s, 25.00 tb(r)
        key = 'Video: '
        for line in lines:
            pos = line.find(key)
            if pos == -1:
                continue
            #mpeg2video, yuv420p, 352x576 [PAR 24:11 DAR 4:3], 2457 kb/s, 25.00 tb(r)
            params = line[pos + len(key):].split(", ")
            self.__info['video'] = {}
            self.__info['video']['codec'] = params[0]
            #2457 kb/s
            #self.__info['video']['bitrate'] = int(params[3].split()[0])
            #25.00 tb(r)
            self.__info['video']['fps'] = float(params[-1].split()[0])
            #52x576 [PAR 24:11 DAR 4:3]
            self.__info['video']['size'] = tuple([int(x) for x in params[2].split()[0].split('x')])
            #352x576
            aspect = self.__info['video']['size']
            if aspect[0] < aspect[1]:
                #swap
                aspect[0], aspect[1] = aspect[1], aspect[0]
            aspect_i = int(aspect[0])/int(aspect[1])
            if aspect_i > 20639:
                # panavision video
                #dvdauthor does not understand panavision aspect ratio (2.35)
                #we must pad the video into widescreen (16:9)
                self.__info['video']['aspect'] = (16, 9)
                self.__info['video']['panavision_pad'] = 50
                self.__info['video']['panavision_size'] = (720, 380)
            elif aspect_i < 15555:
                # normal video
                self.__info['video']['aspect'] = (4, 3)
            else:
                # widescreen video
                self.__info['video']['aspect'] = (16, 9)

    info = property(get_info)
    src = property(get_src, set_src)